package com.ruoyi.common.utils;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import com.ruoyi.common.constant.Constants;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;

public class BigDecimalUtil {
    /**
     * 小数点不进行处理
     */
    public static final int IGNORE_DECIMAL_POINT = -1;

    /**
     * 价格类型 保留小数点 2
     */
    public static final int PRICE_DECIMAL_POINT = 2;

    /**
     * 价格类型 保留小数点 6
     */
    public static final int SIX_PRICE_DECIMAL_POINT = 6;

    /**
     * 重量类型保留小数点 3
     */
    public static final int WEIGHT_DECIMAL_POINT = 3;

    /**
     * 重量类型保留小数点 4
     */
    public static final int ENERGYSC_DECIMAL_POINT = 4;
    /**
     * 价格类型保留小数点 5
     */
    public static final int FIVE_PRICE_DECIMAL_POINT = 5;

    /**
     * 默认值
     * 如果是null 则 返回 0
     * 如果是正常数 则会去掉尾数0 比如 2.000返回2； 2.100返回2.1
     *
     * @param num
     * @return
     */
    public static BigDecimal defaultValue(BigDecimal num) {
        return num == null ? BigDecimal.ZERO : stpTrailZero(num);
    }

    public static BigDecimal defaultValue(BigDecimal num, Integer scale) {
        return num == null ? BigDecimal.ZERO : stpTrailZero(num.setScale(scale, RoundingMode.HALF_EVEN));
    }

    public static BigDecimal defaultValue(double num, Integer scale) {
        return num == 0d ? BigDecimal.ZERO : stpTrailZero(new BigDecimal(num).setScale(scale, RoundingMode.HALF_EVEN));
    }

    /**
     * 去掉num的小数点后的尾0
     * null 还是 null
     * 如果是正常数 则会去掉尾数0 比如 2.000返回2.0； 2.100返回2.1
     *
     * @param num
     * @return
     */
    public static BigDecimal stpTrailZero(BigDecimal num) {
        if (num == null) {
            return num;
        }
        return BigDecimal.valueOf(new BigDecimal(num.stripTrailingZeros().toPlainString()).doubleValue());
    }

    /**
     * 去掉num的小数点后的尾0
     * null 还是 null
     * 如果是正常数 则会去掉尾数0 比如 2.000返回2； 2.100返回2.1
     *
     * @param num
     * @return
     */
    public static BigDecimal toPlain(BigDecimal num) {
        if (ObjUtil.isNotNull(num)) {
            return new BigDecimal(num.stripTrailingZeros().toPlainString());
        }
        return num;
    }

    /**
     *
     *
     * @author liliangbing
     * @param num
     * @return
     */
    public static BigDecimal stpTrailZero1(BigDecimal num) {
        if (num != null) {
            return num.stripTrailingZeros();
        }
        return null;
    }


    /**
     * 判断是否为整数
     *
     * @param num
     * @return
     */
    public static Boolean isInteger(BigDecimal num) {
        if (!"".equals(num) && num != null) {
            if (new BigDecimal(num.intValue()).compareTo(num) == 0) {
                return Boolean.TRUE;
            } else {
                return Boolean.FALSE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 加法：四舍六入五成双 默认保留2位小数点
     */
    public static BigDecimal add(BigDecimal num1, BigDecimal num2) {
        return add(num1, num2, 2);
    }

    /**
     * 加法：四舍六入五成双
     */
    public static BigDecimal add(BigDecimal num1, BigDecimal num2, Integer scale) {
        if (scale < 0) {
            scale = 0;
        }
        return defaultValue(num1).add(defaultValue(num2)).setScale(scale, RoundingMode.HALF_EVEN);
    }

    /**
     * 乘法：四舍六入五成双 默认保留2位小数点
     */
    public static BigDecimal multiply(BigDecimal num1, BigDecimal num2) {
        return multiply(num1, num2, 2);
    }

    /**
     * 乘法：四舍六入五成双
     */
    public static BigDecimal multiply(BigDecimal num1, BigDecimal num2, Integer scale) {
        if (scale < 0) {
            scale = 0;
        }
        return defaultValue(num1).multiply(defaultValue(num2).setScale(scale, RoundingMode.HALF_EVEN));
    }

    /**
     * 减法：四舍六入五成双 默认保留2位小数点
     */
    public static BigDecimal subtract(BigDecimal num1, BigDecimal num2) {
        return subtract(num1, num2, 2);
    }

    /**
     * 减法：四舍六入五成双
     */
    public static BigDecimal subtract(BigDecimal num1, BigDecimal num2, Integer scale) {
        if (scale < 0) {
            scale = 0;
        }
        return defaultValue(num1).subtract(defaultValue(num2)).setScale(scale, RoundingMode.HALF_EVEN);
    }

    /**
     * 除法：四舍六入五成双 默认保留2位小数
     */
    public static BigDecimal divide(BigDecimal num1, BigDecimal num2) {
        return divide(num1, num2, 2);
    }

    /**
     * 除法：四舍六入五成双
     */
    public static BigDecimal divide(BigDecimal num1, BigDecimal num2, Integer scale) {
        if (isEmpty(num1) || isEmpty(num2)) {
            return BigDecimal.ZERO;
        }
        if (scale < 0) {
            scale = 0;
        }
        return num1.divide(num2, 6, RoundingMode.HALF_EVEN).setScale(scale, RoundingMode.HALF_EVEN);
    }


    /**
     * BigDecimal 多值加法 ，结果保留5位小数
     *
     * @param BigDecimal.. args
     *                     BigDecimalUtils.WEIGHT_DECIMAL_POINT
     * @return BigDecimal
     */
    public static BigDecimal addArgs(BigDecimal... args) {
        BigDecimal subResult = new BigDecimal("0");
        if (args != null && args.length > 0) {
            for (BigDecimal b : args) {
                if (isEmpty(b)) {
                    continue;
                } else {
                    subResult = subResult.add(b);
                }
            }
        }
        return setScale(subResult, FIVE_PRICE_DECIMAL_POINT);
    }


    /**
     * 设置小数点位数， 四舍六入五成双
     *
     * @param num
     * @param point
     * @return BigDecimal
     */
    public static BigDecimal setScale(BigDecimal num, int point) {
        return num.setScale(point, RoundingMode.HALF_EVEN);
    }

    /**
     * 比较 num1 是否大于 num2
     *
     * @param num1
     * @param num2
     * @return boolean
     */
    public static boolean isGreaterThan(BigDecimal num1, BigDecimal num2) {
        return num1.compareTo(num2) == 1;
    }

    /**
     * 比较 num1 是否大于等于 num2
     *
     * @param num1
     * @param num2
     * @return boolean
     */
    public static boolean isGreaterOrEqual(BigDecimal num1, BigDecimal num2) {
        return isGreaterThan(num1, num2) || equals(num1, num2);
    }

    /**
     * 比较 num1 是否小于 num2
     *
     * @param num1
     * @param num2
     * @return boolean
     */
    public static boolean isLessThan(BigDecimal num1, BigDecimal num2) {
        return num1.compareTo(num2) == -1;
    }

    /**
     * 比较 num1 是否小于等于 num2
     *
     * @param num1
     * @param num2
     * @return boolean
     */
    public static boolean isLessOrEqual(BigDecimal num1, BigDecimal num2) {
        return isLessThan(num1, num2) || equals(num1, num2);
    }

    /**
     * 比较 num1 是否等于 num2
     *
     * @param num1
     * @param num2
     * @return
     */
    public static boolean equals(BigDecimal num1, BigDecimal num2) {
        return num1.compareTo(num2) == 0;
    }

    /**
     * 计算 num1 / num2 的百分比
     *
     * @param num1
     * @param num2
     * @return String
     */
    public static String getPercentage(BigDecimal num1, BigDecimal num2) {
        BigDecimal result = divide(num1, num2, 4);
        NumberFormat percent = NumberFormat.getPercentInstance();
        percent.setMaximumFractionDigits(2);
        return percent.format(result.doubleValue());
    }

    /**
     * 计算 num1 / num2 的百分比
     *
     * @param num1
     * @param num2
     * @param point 保留几位小数
     * @return String
     */
    public static BigDecimal bigDecimalPercent(Integer num1, Integer num2, int point) {
        if (num1 == null || num2 == null) {
            return BigDecimal.ZERO;
        }
        if (num2.equals(Integer.valueOf(0))) {
            return BigDecimal.ZERO;
        }
        BigDecimal bigDecimalNum1 = new BigDecimal(num1);
        BigDecimal bigDecimalNum2 = new BigDecimal(num2);
        return bigDecimalPercent(bigDecimalNum1, bigDecimalNum2, point);
    }

    /**
     * 计算 num1 / num2 的百分比
     *
     * @param num1
     * @param num2
     * @param point 保留几位小数
     * @return String
     */
    public static BigDecimal bigDecimalPercent(BigDecimal num1, BigDecimal num2, int point) {
        if (num1 == null || num2 == null) {
            return BigDecimal.ZERO;
        }
        if (equals(BigDecimal.ZERO, num2)) {
            return BigDecimal.ZERO;
        }
        BigDecimal percent = num1.divide(num2, point + 2, RoundingMode.HALF_EVEN);
        BigDecimal percent100 = percent.multiply(new BigDecimal(100)).setScale(point);
        return percent100;
    }

    /**
     * 判断num是否为空 或者 零
     *
     * @param num
     * @return String
     */
    public static Boolean isEmpty(BigDecimal num) {
        return null == num || equals(BigDecimal.ZERO, num);
    }


    /**
     * 判断num是否 不等于null 并且不等于零
     *
     * @param num
     * @return String
     */
    public static Boolean isNotEmpty(BigDecimal num) {
        return !isEmpty(num);
    }

    /**
     * 有任何一个数字为null  则返回false
     * @param num
     * @return
     */
    public static Boolean isAnyOneEmpty(BigDecimal... num) {
        for (BigDecimal decimal : num) {
            if (null == decimal) {
                return true;
            }
        }
        return false;
    }


    /**
     * 将BigDecimal对象转换为字符串表示形式
     * 此方法主要用于处理null值，避免直接调用BigDecimal的toPlainString方法时出现NullPointerException异常
     *
     * @param decimal 待转换的BigDecimal对象，可以为null
     * @return 如果decimal不为null，则返回其字符串表示形式；否则返回null
     */
    public static String toString(BigDecimal decimal) {
        // 检查输入的BigDecimal对象是否为null
        if (decimal != null) {
            // 如果不为null，则使用BigDecimal的toPlainString方法转换为字符串
            return decimal.toPlainString();
        }
        // 如果为null，则直接返回null
        return null;
    }

    /**
     * 将BigDecimal对象转换为字符串，如果对象为null，则返回空字符串
     * 这个方法的目的是避免直接调用BigDecimal的toString方法时，可能因为对象为null而引发NullPointerException
     *
     * @param decimal 待转换的BigDecimal对象
     * @return 如果decimal不为null，则返回其字符串表示形式；否则返回空字符串
     */
    public static String toStringDefaultEmpty(BigDecimal decimal) {
        // 检查输入的BigDecimal对象是否为null
        if (decimal != null) {
            // 如果不为null，则使用BigDecimal的toPlainString方法转换为字符串
            return decimal.toPlainString();
        }
        // 如果为null，则返回空字符串
        return "";
    }
}
